// Core.js

// DO NOT MODIFY THIS SCRIPT.
// This script contains key functions for decompiling and re-compiling AMF data.

// deserializes amf value
function amfDeserialize(dataObj) {
	var returnValue;
	var typeOf = asc(dataObj.data.substr(0, 1));
	dataObj.data = dataObj.data.substr(1);
	switch (typeOf) {
	case 0: // number
		returnValue = numberDeserialize(dataObj.data.substr(0, 8));
		dataObj.data = dataObj.data.substr(8);
	break;
	case 1: // boolean
		returnValue = new Boolean(asc(dataObj.data.substr(0, 1)));
		dataObj.data = dataObj.data.substr(1);
	break;
	case 2: // string
		returnValue = getAmfString(dataObj);
	break;
	case 3: // object marker
		returnValue = amfObjectDeserialize(dataObj);
	break;
	case 5: // null
		returnValue = 0;
	break;
	case 6: // undefined
		returnValue = undefined;
	break;
	case 8: // ecma array marker
		dataObj.data = dataObj.data.substr(4);
		returnValue = amfObjectDeserialize(dataObj);
	break;
	case 10: // strict array marker
		var arrayCount = bytesToInt(dataObj.data.substr(0,4));
		dataObj.data = dataObj.data.substr(4);
		returnValue = new Object();
		for (var j = 0; j < arrayCount; j++)
			returnValue[j] = amfDeserialize(dataObj);
	break;
	case 11: // date
		returnValue = dataObj.data.substr(0, 10);
		dataObj.data = dataObj.data.substr(10);
	break;
	case 13: // unsupported
		returnValue = undefined;
	break;
	default:
		addText("ERROR DESERIALIZING DATA!\r\ntypeOf: " + typeOf + "\r\nData: " + stringReplace(dataObj.data, chr(0), "."), true);
		doClose();
	}
	return returnValue;
}

// deserializes amf object
function amfObjectDeserialize(dataObj) {
	var msgObj = new Object();
	var objName;
	while (true) {
		objName = getAmfString(dataObj);
		if (objName.length) {
			msgObj[objName] = amfDeserialize(dataObj);
		} else {
			dataObj.data = dataObj.data.substr(1);
			return msgObj;
		}
	}
}

// serializes an object into an amf object.
function amfSerialize(obj) {
	var amfObj;
	switch (typeof obj) {
	case "number":
		amfObj = chr(0) + numberSerialize(obj);
	break;
	case "boolean":
		amfObj = chr(1) + chr(obj);
	break;
	case "string":
		amfObj = chr(2) + stringSerialize(unicodeToUtf8(obj));
	break;
	case "object":
		if (obj != null) {
			amfObj = chr(3);
			for (var paramName in obj)
				amfObj += stringSerialize(paramName.toString()) + amfSerialize(obj[paramName]);
			amfObj += chr(0) + chr(0) + chr(9);
		} else { // "null"
			amfObj = chr(5);
		}
	break;
	case "undefined":
		amfObj = chr(6);
	break;
	default: // "unsupported"
		amfObj = chr(13);
		addColorText("Serialization error: Unsupported type (" + (typeof obj) + ")", "Red", true);
	}
	return amfObj;
}

// gets first charCode in a unicode string.
function asc(str) {
	return str.charCodeAt(0);
}

// generates a unicode character.
function chr(charCode) {
	return String.fromCharCode(charCode);
}

// lists object's inner variables.
function debugObject(functionName, msgObj) {
	addColorText("Debugging object for \"" + functionName + "\" - ", "Green", true);
	// var msg = "";
	// msg += "\n" + i + ": " + msgObj[i];
	// Client_sendChatMessage(msg);
	for (i in msgObj)
		addColorText(i + ": " + msgObj[i], "Orange", true);
}

// send "doServer" invoke to server.
function doServer(msgObj) {
	sendData(dataGram(3, randomTimeStamp(), 20, 0, invoke(["doServer", 0, null, msgObj])));
}

// get amf string.
function getAmfString(dataObj) {
 	var strLen = bytesToInt(dataObj.data.substr(0, 2));
	var str = utf8ToUnicode(dataObj.data.substr(2, strLen));
	dataObj.data = dataObj.data.substr(strLen + 2);
	return str;
}

// gets object by type.
function getObjectByType(obj, typeOf) {
	var returnValue;
	for (var i in obj)
		if ((typeof obj[i]) == typeOf)
			returnValue = obj[i];
	return returnValue;
}

// generates invoke to be used inside of a datagram.
function invoke(objArray) {
	var invokeData = "";
	for (var i in objArray)
		invokeData += amfSerialize(objArray[i]);
	return invokeData;
}

// parse amf invoke into an objArray.
function parseInvoke(dataObj) {
	var i = 0;
	var objArray = [];
	while (dataObj.data.length) {
		objArray[i] = amfDeserialize(dataObj);
		i++;
	}
	return objArray;
}

// returns a proper boolean value from any object.
function properBoolean(obj) {
	if (obj == true)
		return true;
	else
		return false;
}